package com.wzy.ucenter.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wzy.ucenter.mapper.XcUserMapper;
import com.wzy.ucenter.mapper.XcUserRoleMapper;
import com.wzy.ucenter.model.dto.AuthParamsDto;
import com.wzy.ucenter.model.dto.XcUserExt;
import com.wzy.ucenter.model.po.XcUser;
import com.wzy.ucenter.model.po.XcUserRole;
import com.wzy.ucenter.service.AuthService;
import com.wzy.ucenter.service.WeChatAuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;

/**
 * @Author wzy
 * @Date 2024/1/29 15:18
 * @description: 微信登录认证
 */
@Slf4j
@Service("wx_authService")
public class weChatAuthServiceImpl implements AuthService , WeChatAuthService {
    @Autowired
    XcUserMapper xcUserMapper;

    @Autowired
    RestTemplate restTemplate;
    @Autowired
    private weChatAuthServiceImpl weChatAuthService;
    @Autowired
    private XcUserRoleMapper xcUserRoleMapper;

    @Value("${weixin.appid}")
    String appid;//应用唯一标识
    @Value("${weixin.secret}")
    String secret;//应用秘钥


    @Override
    public XcUserExt execute(AuthParamsDto authParamsDto) {

        //账号
        String username = authParamsDto.getUsername();
        //查询数据库
        XcUser user = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().eq(XcUser::getUsername, username));
        if(user==null){
            //返回空表示用户不存在
            throw new RuntimeException("账号不存在");
        }
        XcUserExt xcUserExt = new XcUserExt();
        BeanUtils.copyProperties(user,xcUserExt);
        return xcUserExt;
    }

    /**
     * 获取微信用户登录信息
     * @param code 微信授权码
     * @return
     */
    @Override
    public XcUser wxAuth(String code) {
        //1.根据授权码向微信申请令牌
        //收到code调用微信接口申请access_token
        Map<String, String> access_token_map = getAccess_token(code);
        if(CollectionUtils.isEmpty(access_token_map)){
            return null;
        }
        //2.根据令牌查询微信用户信息
        String openid = access_token_map.get("openid");//授权用户唯一标识
        String access_token = access_token_map.get("access_token");//用户登录凭证
        //拿access_token查询用户信息
        Map<String, String> userinfo = getUserinfo(access_token, openid);
        if(userinfo==null){
            return null;
        }
        //3.将用户信息写入数据库
        XcUser xcUser = weChatAuthService.addWxUser(userinfo);
        return xcUser;
    }

    /**
     * 将微信用户信息插入数据库
     * @param userinfo 通过微信接口查询到的用户信息
     * @return
     */
    @Transactional
    public XcUser addWxUser(Map<String, String> userinfo) {
        // unionid	用户统一标识。针对一个微信开放平台账号下的应用，同一用户的unionid是唯一的。
        String unionid = userinfo.get("unionid");
        // 通过unionid查询数据库中是否已有该用户
        LambdaQueryWrapper<XcUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(XcUser::getWxUnionid,unionid);
        XcUser xcUser = xcUserMapper.selectOne(lambdaQueryWrapper);
        if(xcUser!=null){
            return xcUser;
        }
        //如果查询出的用户为空 说明数据库中没有 则插入数据库
        String userId = UUID.randomUUID().toString();//主键
        xcUser = new XcUser();
        xcUser.setId(userId);
        xcUser.setWxUnionid(unionid);
        //记录从微信得到的昵称
        xcUser.setNickname(userinfo.get("nickname").toString());//普通用户昵称
        xcUser.setUserpic(userinfo.get("headimgurl").toString());//用户头像
        xcUser.setName(userinfo.get("nickname").toString());
        xcUser.setUsername(unionid);
        xcUser.setPassword(unionid);
        xcUser.setUtype("101001");//学生类型
        xcUser.setStatus("1");//用户状态
        xcUser.setCreateTime(LocalDateTime.now());
        xcUserMapper.insert(xcUser);
        //向关系角色表插入数据
        XcUserRole xcUserRole = new XcUserRole();
        xcUserRole.setId(UUID.randomUUID().toString());
        xcUserRole.setUserId(userId);
        xcUserRole.setCreateTime(LocalDateTime.now());
        xcUserRole.setRoleId("17");//学生角色
        xcUserRoleMapper.insert(xcUserRole);
        return xcUser;

    }

    /**
     * 获取微信登录用户信息
     * 请求微信接口地址：
     * http请求方式: GET
     * https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
     * @param accessToken 用户登录凭证
     * @param openid 用户唯一标识
     * @return
     */
    private Map<String, String> getUserinfo(String accessToken, String openid) {
        String wxUrl_template = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
        //请求微信地址
        String wxUrl = String.format(wxUrl_template, accessToken,openid);
        log.info("调用微信接口申请access_token, url:{}", wxUrl);
        ResponseEntity<String> exchange = restTemplate.exchange(wxUrl, HttpMethod.POST, null, String.class);
        //防止乱码进行转码
        String result = new     String(exchange.getBody().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        log.info("调用微信接口申请access_token: 返回值:{}", result);
        Map<String,String> resultMap = JSON.parseObject(result, Map.class);

        return resultMap;

    }

    /**
     * 根据授权码申请令牌
     * 微信申请授权码接口地址：
     * https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
     * @param code 登录授权码
     * @return
     */
    private Map<String,String> getAccess_token(String code) {
        String wxUrl_template = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
        //请求微信地址
        String wxUrl = String.format(wxUrl_template, appid, secret, code);
        log.info("调用微信接口申请access_token，url：{}",wxUrl);
        ResponseEntity<String> exchange = restTemplate.exchange(wxUrl, HttpMethod.POST, null, String.class);
        String result = exchange.getBody();//返回的是json数据
        log.info("调用微信接口申请access_token，返回值：{}",result);
        //将json数据装换为map集合
        Map<String,String> resultMap = JSON.parseObject(result, Map.class);
        return resultMap;
    }
}
